package cn.kgc.commons.advice;

import cn.kgc.base.entity.SysDict;
import cn.kgc.base.entity.SysDictItem;
import cn.kgc.base.mapper.SysDictItemMapper;
import cn.kgc.base.mapper.SysDictMapper;
import cn.kgc.commons.annotation.Dict;
import cn.kgc.commons.constant.SysDictItemStatus;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * @description: 翻译返回值的常量
 * @author: 石浩杰
 * @date: 2022-11-30 15:56
 */
@Aspect
@Component
@Slf4j
public class AutoDictAdvice {

    @Resource
    private SysDictMapper sysDictMapper;

    @Resource
    private SysDictItemMapper sysDictItemMapper;

    @Pointcut("@annotation(cn.kgc.commons.annotation.AutoDict)")
    public void autoDictPointCut(){}

    @Around("autoDictPointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
        //调用目标方法
        Object result=joinPoint.proceed();
        result=parseResultDictText(result);
        return result;
    }

    /**
     * 解析返回值的字典文本
     * @param result
     * @return
     */
    private Object parseResultDictText(Object result)throws Exception{
        //目标方法返回的是分页数据
        if (result instanceof IPage){
            ObjectMapper objectMapper=new ObjectMapper();
            //获得分页数据
            List<Object> objectList=((IPage) result).getRecords();
            //存储翻译后的数据
            List<JSONObject> resultList=new ArrayList<>();
            //解析分页数据
            for (Object o : objectList) {
                String json=objectMapper.writeValueAsString(o);
                //将原有的每条数据转为JSONObject类型的。JSONObject对象中的属性值来自原有的每条数据（可以很方便的给JSONObject属性添加对象）
                JSONObject jsonObject=JSONObject.parseObject(json, Feature.OrderedField);
                //原有属性上是否含有@Dict注解,如果有，就进行字典转换
                Field [] fields=o.getClass().getDeclaredFields();
                for(Field temp:fields){
                    //原属性的返回修饰符是私有的，调用该方法可以让私有属性也可以被访问
                    temp.setAccessible(true);
                    //判断原属性上是否有@Dict注解
                    if(temp.isAnnotationPresent(Dict.class)){
                        Dict dict=temp.getAnnotation(Dict.class);
                        String dictCode=dict.dictCode();//字典编码
                        String fieldName=temp.getName();//原属性名
                        String fieldValue=jsonObject.get(fieldName).toString();//原属性的值
                        //根据字典编码查询字典（sys_dict）
                        LambdaQueryWrapper<SysDict> dictQueryWrapper=new LambdaQueryWrapper<>();
                        dictQueryWrapper.eq(SysDict::getDictCode,dictCode);
                        SysDict sysDict=sysDictMapper.selectOne(dictQueryWrapper);
                        if(sysDict!=null){
                            Long sysDictId=sysDict.getId();
                            LambdaQueryWrapper<SysDictItem> dictItemQueryWrapper=new LambdaQueryWrapper<>();
                            dictItemQueryWrapper.eq(SysDictItem::getDictId,sysDictId);
                            dictItemQueryWrapper.eq(SysDictItem::getItemValue,fieldValue);
                            dictItemQueryWrapper.eq(SysDictItem::getStatus, SysDictItemStatus.ENABLE.getStatus());
                            SysDictItem sysDictItem=sysDictItemMapper.selectOne(dictItemQueryWrapper);
                            if(sysDictItem!=null){
                                //新的属性的值
                                String dictItemText=sysDictItem.getItemText();
                                //新的属性名
                                fieldName+="_txt";
                                jsonObject.put(fieldName,dictItemText);
                            }
                        }

                    }
                }
                resultList.add(jsonObject);
            }
            ((IPage) result).setRecords(resultList);
        }
        return result;
    }

}
